
/**
 * wf.c
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "WordObj.h"
#include "Node.h"
#include "List.h"

const int MAX_LINE_LENGTH = 2048;
const char * delimiters = " 0123456789\t;{}()[].#<>\n\r+-/%*\"^~&=!|:\\?,";

//Prototype for function that converts string to lowercase
char * strToLower(char *str);



//Create function that converts String to lowercase
char * strToLower(char *str){
        
    //Variable for looping
    char *p;
  
    //Loop through each character of the string and use the standard library function
    //tolower() to convert that character to lowercase. This function uses
    //pointer arithmetic to move through the string.
        
    for (p = str; *p != '\0'; ++p){
       *p = tolower(*p);
    }
    
    return str;
}



int main(int argc, char *argv[]) {

	//First make sure there are 2 command-line arguments. If not, exit.
	if(argc != 3){
	  printf("\nUsage: wf {--self-organized-list|--std-list} <textfile>\n\n");
	  return 0; //End Program. No need to go on.
	}
  
  
	//Make sure the command-line arguments are correct before continuing
	if( strcmp(argv[1],"--self-organized-list") != 0 && strcmp(argv[1],"--std-list") != 0 ){
	    printf("\nUsage: wf {--self-organized-list|--std-list} <textfile>\n\n");
		return 0; //End Program. No need to go on.
	}
	
	//Create and set a flag to signify if this should be a self-organizing list.
	//The flag will be 1 if it is supposed to be self-organizing, or 0 if it isn't
	short int selfOrganizing;
	
	if(strcmp(argv[1],"--self-organized-list") == 0){
	    selfOrganizing = 1;
	}
	else{
	    selfOrganizing = 0;
	}
	
	//Create a node pointer variable
	NodePtr node;
	
	//Create a Word Object Pointer Variable
	WordObjPtr wordObject;
	
	
	
	//Attempt to open the text file provided
	
	//Create a pointer to a FILE
	FILE * file;
	
	file = fopen(argv[2],"r");
	
	//If no error is encountered, process the file.
	//fopen() returns NULL on an error, so that's what we'll check for
	if(file != NULL){
	  //Create a variable to hold each line of text
	  char line[MAX_LINE_LENGTH+1];
	  
	  //Create variable to hold tokens
	  char *token;
	  
	  //Create the linked list
	  ListPtr list;
	  list = createList(equals,toString,freeWordObj);
	  	  
	  //Process each line of the text file
	  while (fgets(line, MAX_LINE_LENGTH, file)) {
	      //Process the line
	      
	      //First we will tokenize the line to get each Word
	      token = strtok(line, delimiters);
	      while (token != NULL){
		   //Convert to lowercase
		   token = strToLower(token);
		   
		   //Add word to the list if it isn't already there.
		   //If it is already there, just update the frequency.
		   
		   
		   //Search the list for the word
		   if(search(list,token) != NULL){ //Then we know the word is in the list
			
		     //Get the node it is in and Increment the frequency
		        node = search(list,token);
			wordObject = node->obj;
			wordObject->frequency++;
			
			//If this is a self-organizing list, move the node to the front
			if(selfOrganizing){
			    //Remove node from list first
			    node = removeNode(list,node);
			    
			    //Now add it back to the front
			    addAtFront(list,node);
			}
			
		   }
		   else{ //The word is not in the list yet, so we need to add it
		      //First create the word object with a frequency of 1 since this is the first time we've seen this word
		      wordObject = createWordObj(token,1);
		      
		      //Now enter than object into a new node
		      node = createNode(wordObject);
		      
		      //Now add this to the rear of the list.
		      //I'm adding to the rear instead of the front just in case this is self-organized list
		      //we won't push all the ones we moved to the front back.
		      addAtRear(list,node);
		   }
		     
		   
		   
		   
		   token = strtok(NULL,  delimiters);
	      }
	      
	      
	  }
	  
	  //Close File
	  fclose(file);
	  
	  //Now print out the list
		    NodePtr temp = list->head; 
		    NodePtr nextNode; 
		    
		    //Create pointer variable so we can free each string after printing
		    char *printedLine;
		    
		    while(temp != NULL){
			printedLine = toString(temp->obj);
			
			printf("%s\n",printedLine);
			
			//Now free the memory pointed to by printedLine because the toString()
			//function used malloc() to save the string in the heap. This avoids memory leaks.
			free(printedLine);
			//Set it to NULL so it isn't a dangling pointer
			printedLine = NULL;
				
			nextNode = temp->next;
			temp = nextNode;
		    }
		    
	  //Free the list
	  freeList(list);
	  
	}
	else{ //There was an error. Exit.
	   printf("\nThere was an error opening %s\n\n",argv[2]);
	   return 0; //Exit
	}
	
	return 0;
}
